package nl.saxion.security.connection;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.StreamCorruptedException;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * Class for setting up connection
 * @author EII7SCb
 *
 */
public class Connection {

	protected int port;
	protected Socket connection = null;
	protected OutputStream out = null;
	protected InputStream in = null;
	protected int timeOut;

	private int BUFFERSIZE = 8192;
	
	/**
	 * Set parameters
	 * @param port
	 * @param timeOut
	 */
	public Connection(int port, int timeOut)
	{
		this.port = port;
		this.timeOut = timeOut;
	}
	
	/**
	 * Gets the available bytes on the stream
	 * @return
	 * @throws IOException 
	 */
	public byte[] readData() throws IOException
	{
		byte[] data = null;
		
		if(!isConnected())
			return data;
		BufferedInputStream bis = new BufferedInputStream(in, BUFFERSIZE); 
		
		while(bis.available() <= 0){}
		
		
		data = new byte[bis.available()];			
		bis.read(data);

		return data;	
	}
	
	/**
	 * Gets the available bytes on the stream no check if there is data
	 * @return data
	 * @throws IOException 
	 */
	public byte[] readData2() throws IOException
	{
		byte[] data = null;
		
		if(!isConnected())
			return data;
		BufferedInputStream bis = new BufferedInputStream(in, BUFFERSIZE); 	
		
		data = new byte[bis.available()];			
		bis.read(data);

		return data;	
	}
	

	/**
	 * Check if there is data available
	 * @return
	 * @throws IOException
	 */
	public boolean dataOnLine() throws IOException
	{

		if(!isConnected())
			return false;
		BufferedInputStream bis = new BufferedInputStream(in, BUFFERSIZE); 	
		
		if(bis.available()> 0)
				return true;
		else
				return false;
	}
	
	/**
	 * Gets the object form the inputstream. No check if the bytes on the stream represent a Object
	 * @return the Object
	 * @throws StreamCorruptedException
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	public Object getObject() throws StreamCorruptedException, IOException, ClassNotFoundException
	{
		Object object = null;
		if(!isConnected())
			return object;
	
		ObjectInputStream ois = new ObjectInputStream(in);
		object = ois.readObject();
		//ois.close();
		
		return object;	
	}
	
	
	/**
	 * Send bytes to stream
	 * @param data
	 * @return true if success
	 * @throws IOException
	 */
	public boolean sendData(byte[] data) throws IOException
	{

		if(!isConnected())
			return false;
	
		
		out.write(data);
		out.flush();
		return true;
				
	}
	
	/**
	 * Get file from stream.
	 * @param fileName location to write the file to
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public boolean getFile(String fileName)  throws FileNotFoundException, IOException
	{
		if(!isConnected())
			return false;
		
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));
		BufferedInputStream bis = new BufferedInputStream(in, BUFFERSIZE); 	
		
		byte[] buffer = new byte[1024];
		int bytesRead = 0;
		 while ((bytesRead = bis.read(buffer)) != -1) 
		 {
			 bos.write(buffer, 0, bytesRead);  
		 }

		bos.close();
		bis.close();
		this.close();
		return true;
	}
	
	
	/**
	 * Send the bytes from the file to outputstream
	 * @param file
	 */
	public boolean sendFile(File file)  throws FileNotFoundException, IOException
	{

		if(!isConnected())
			return false;

		BufferedInputStream  bis = new BufferedInputStream(new FileInputStream(file), BUFFERSIZE);	
		BufferedOutputStream bos = new BufferedOutputStream(out);
		byte[] data = new byte[(int) file.length()];
		bis.read(data);
		bos.write(data);
		bos.flush();
		bos.close();
		bis.close();
		return true;
	}
	
	
	/**
	 * Send object to stream
	 * @param object
	 * @return True if success
	 * @throws IOException
	 */
	public boolean sendObject(Object object) throws IOException {
		
		if(!isConnected())
			return false;
		
		ObjectOutputStream oos = new ObjectOutputStream(out);		
		oos.writeObject(object);		
		return true;
	}
	
	/**
	 * close connection
	 * @throws IOException
	 */
	public void close() throws IOException
	{
		in.close();
		out.close();
		connection.close();
	}

	
	/**
	 * 
	 * @return true is connected 
	 */
	public boolean isConnected() 
	{
		if(connection != null && connection.isConnected())
			return true;
		else{
			return false;
		}	
	}
	
	/**
	 * Create connection
	 * @return
	 * @throws IOException
	 * @throws InterruptedException
	 */
	public boolean makeConnection() throws IOException, InterruptedException
	{
		connection.setSoTimeout(0); //timeout
		return false;
	}
	
}
